package bootstrap

import (
	_ "ginstudy/app/core/destroy" // 监听程序退出信号，用于资源的释放
	my_errors "ginstudy/app/global/my_errors"
	"ginstudy/app/global/variable"
	"ginstudy/app/http/validator/common/register_validator"
	sys_log_hook "ginstudy/app/service/sys_log_hook"
	gorm_v2 "ginstudy/app/utils/gorm_v2"
	"ginstudy/app/utils/yml_config"
	"ginstudy/app/utils/zap_factory"
	"log"
	"os"
)

// 检查项目必须的非编译目录是否存在，避免编译后调用的时候缺失相关目录
func checkRequiredFolders() {
	// 1.检查配置文件是否存在
	if _, err := os.Stat(variable.BasePath + "\\config\\config.yml"); err != nil {
		log.Fatal(my_errors.ErrorsConfigYamlNotExists + err.Error())
	}
	if _, err := os.Stat(variable.BasePath + "\\config\\gorm_v2.yml"); err != nil {
		log.Fatal(my_errors.ErrorsConfigGormNotExists + err.Error())
	}
	// 2.检查public目录是否存在
	if _, err := os.Stat(variable.BasePath + "\\public\\"); err != nil {
		log.Fatal(my_errors.ErrorsPublicNotExists + err.Error())
	}
	// 3.检查storage/logs 目录是否存在
	if _, err := os.Stat(variable.BasePath + "\\storage\\logs\\"); err != nil {
		log.Fatal(my_errors.ErrorsStorageLogsNotExists + err.Error())
	}
	// 4.自动创建软连接，更好的管理静态资源
	if _, err := os.Stat(variable.BasePath + "\\public\\storage"); err == nil {
		if err = os.RemoveAll(variable.BasePath + "\\public\\storage"); err != nil {
			log.Fatal(my_errors.ErrorsSoftLinkDeleteFail + err.Error())
		}
	}
	if err := os.Symlink(variable.BasePath+"\\storage\\app", variable.BasePath+"\\public\\storage"); err != nil {
		log.Fatal(my_errors.ErrorsSoftLinkCreateFail + err.Error())
	}
}

func init() {
	// 1. 初始化 项目根路径，参见 variable 常量包， app\global\variable\variable.go

	// 2. 检查配置文件以及日志目录等非编译性的必要条件
	checkRequiredFolders()

	// 3. 初始化表单参数验证器，注册在容器（Web、Api共用容器）
	register_validator.WebRegisterValidator()

	// 4. 启动针对配置文件(config.yml、gorm_v2.yml)变化的监听，配置文件操作指针初始化为全局变量
	variable.ConfigYml = yml_config.CreateYamlFactory()
	variable.ConfigYml.ConfigFileChangeListen()
	// config>gorm_v2.yml 启动文件变化监听事件
	variable.ConfigGormv2Yml = variable.ConfigYml.Clone("gorm_v2")
	variable.ConfigGormv2Yml.ConfigFileChangeListen()

	// 5. 初始化全局日志句柄，并载入日志钩子处理函数
	variable.ZapLog = zap_factory.CreateZapFactory(sys_log_hook.ZapLogHandler)

	// 6. 根据配置初始化 gorm mysql 全局 *gorm.Db
	if variable.ConfigGormv2Yml.GetInt("Gormv2.Mysql.IsInitGolobalGormMysql") == 1 {
		if dbMysql, err := gorm_v2.GetOneMysqlClient(); err != nil {
			log.Fatal(my_errors.ErrorsGormInitFail + err.Error())
		} else {
			variable.GormDbMysql = dbMysql
		}
	}
}
